const readline = require('readline');
const FormData = require('form-data');  // 引入 form-data 库
const yargs = require('yargs');
const axios = require('axios');
const path = require('path');
const fs = require('fs');

// 初始配置
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  prompt: `${process.cwd()}> ` // 显示当前目录
});

// 解析命令行参数
const argv = yargs
  .scriptName('')  // 这将去掉命令行中显示脚本名（test.js）
  .option('host', { default: '127.0.0.1' })//这里是你的服务器地址，eg：192.168.109.129
  .option('port', { default: 8080 })//这里是你的服务器开启服务的端口号
  .option('user', { default: 'zs' })
  .option('pwd', { default: 'ddd' })
  .help('help')
  .alias('help', 'h')
  // 添加每个命令的描述
  .command('upload <file>', '上传本地当前目录的文件到服务器的当前目录')
  .command('download <file>', '下载服务器当前目录的文件到本地当前目录')
  .command('delete <file>', '删除服务器当前目录的文件')
  .command('rename <file-old> <file-new>', '修改服务器当前目录的文件名')
  .command('mkdir <dir>', '在服务器当前目录，创建子目录')
  .command('delete <dir>', '删除服务器当前目录下的子目录，支持递归删除')
  .command('rename <dir-old> <dir-new>', '修改服务器当前目录下的子目录名称')
  .command('list', '查看服务器当前目录下的文件或目录，目录名后面加 `/`')
  .command('lcd <dir>', '修改本地当前目录，仅支持绝对路径')
  .command('lpwd', '打印本地当前目录的绝对路径')
  .command('rcd <dir>', '修改服务器当前目录，仅支持绝对路径')
  .command('rpwd', '打印服务器当前目录的绝对路径')
  .command('<file>','代表本地文件或服务器文件')
  .command('<dir>','代表本地目录或服务器目录')
  .argv;

// 初始化客户端连接配置
const serverURL = `http://${argv.host}:${argv.port}`;
console.log(`连接到服务器: ${serverURL}，用户：${argv.user}`);

// 保存 token
let authToken = '';

// 登录函数
async function login() {
  try {
    const response = await axios.post(`${serverURL}/api/users/login`, {
      username: argv.user,
      password: argv.pwd
    });
    if (response.data.status === 0) {
      console.log('登录成功');
      authToken = response.data.token;  // 保存 token
      return true; // 登录成功，返回 true
    } else {
      console.log('登录失败:', response.data.msg);
      return false; // 登录失败，返回 false
    }
  } catch (error) {
    console.error('登录失败:', error.response?.data?.msg || error.message);
    return false; // 登录失败，返回 false
  }
}

// 等待登录成功后，才开始进入命令行界面
async function startCLI() {
  const isLoggedIn = await login(); // 调用登录函数

  if (isLoggedIn) {
    // 登录成功后，开始接受命令行输入
    rl.prompt();
    rl.on('line', async (line) => {
      const input = line.trim().split(' '); // 分割输入命令
      const command = input[0]; // 获取命令
      const args = input.slice(1); // 获取命令的参数

      try {
        // 解析输入命令并调用相应的处理函数
        switch (command) {
          case 'upload':
            await uploadFile(args[0]);
            break;
          case 'download':
            await downloadFile(args[0]);
            break;
            //成功，创建远程目录

          case 'mkdir':
            await createDirectory(args[0]);
            break;
            //开始尝试，递归删除之类,删除远程文件及文件夹，成功
          case 'delete':
            await deleteFile(args[0]);
            break;
            //重命名远程服务器子目录名称,文件，成功
          case 'rename':
            await renameFile(args[0], args[1]);
            break;
            //成功
          case 'list':
            await listFiles();
            break;
          // 修改本机当前目录以及路径,成功
          case 'lcd':
            const newDir = args[0];
            if (newDir && fs.existsSync(newDir) && fs.statSync(newDir).isDirectory()) {
              process.chdir(newDir); // 改变当前目录
              console.log(`成功切换到目录: ${process.cwd()}`);
            } else {
              console.log(`错误: 目录 "${newDir}" 不存在或无效`);
            }
            break;
          case 'lpwd':
            console.log(`本地当前路径: ${process.cwd()}`);
            break;
            //修改远程当前目录以及打印绝对路径，成功
          case 'rcd':
            await changeDirectory(args[0]);
            break;
            case 'rpwd':
              await printRemotePath();  // 处理 `rpwd` 命令
              break;
          default:
            console.log(`未知命令: ${command}`);
        }
      } catch (error) {
        console.error('命令执行失败:', error.message);
      }

      rl.prompt(); // 提示输入下一条命令
    });
  } else {
    console.log('无法登录，请检查用户名和密码。');
    rl.close(); // 关闭命令行接口
    process.exit(1); // 退出程序
  }
}

// 文件上传函数
async function uploadFile(fileName) {
  const filePath = path.join(process.cwd(), fileName);
  if (fs.existsSync(filePath)) {
    try {
      const formData = new FormData();
      formData.append('file', fs.createReadStream(filePath), fileName); // 第二个参数传入文件名

      // 设置上传请求头，确保正确处理 multipart/form-data
      const response = await axios.post(`${serverURL}/api/files/upload`, formData, {
        headers: {
          'Authorization': `Bearer ${authToken}`,
          ...formData.getHeaders() // 使用 form-data 的默认头部
        },
      });
      console.log(response.data.msg);
    } catch (error) {
      console.error('上传失败:', error.response?.data?.msg || error.message);
    }
  } else {
    console.log('文件不存在:', fileName);
  }
}


// 文件下载函数
async function downloadFile(fileName) {
  try {
    const response = await axios.get(`${serverURL}/api/files/download/${fileName}`, { 
      responseType: 'stream',
      headers: { 'Authorization': `Bearer ${authToken}` }  // 添加 Authorization 头
    });

    const writer = fs.createWriteStream(path.join(process.cwd(), fileName));
    response.data.pipe(writer);

    writer.on('finish', () => {
      console.log(`文件下载完成: ${fileName}`);
      rl.prompt();  // 确保文件下载完成后继续提示用户输入命令
    });

    writer.on('error', (err) => {
      console.error('下载失败:', err.message);
      rl.prompt();  // 发生错误后也继续提示用户输入命令
    });
  } catch (error) {
    console.error('下载失败:', error.response?.data?.msg || error.message);
    rl.prompt();  // 错误发生后继续提示用户输入命令
  }
}



// 删除目录函数
async function deleteFile(fileName) {
  try {
    const response = await axios.delete(`${serverURL}/api/files/delete/${fileName}`, {
      headers: { 'Authorization': `Bearer ${authToken}` }  // 添加 Authorization 头
    });
    console.log(response.data.msg);
  } catch (error) {
    console.error('删除失败:', error.response?.data?.msg || error.message);
  }
}

// 重命名文件函数
async function renameFile(oldName, newName) {
  try {
    const response = await axios.put(`${serverURL}/api/files/rename`, {
      oldName,
      newName,
    }, {
      headers: { 'Authorization': `Bearer ${authToken}` }  // 添加 Authorization 头
    });
    console.log(response.data.msg);
  } catch (error) {
    console.error('重命名失败:', error.response?.data?.msg || error.message);
  }
}

// 创建远程目录函数
async function createDirectory(dirName) {
  try {
    const response = await axios.post(`${serverURL}/api/dirs/create`, { dirName }, {
      headers: { 'Authorization': `Bearer ${authToken}` }  // 添加 Authorization 头
    });
    console.log(response.data.msg);
  } catch (error) {
    console.error('创建目录失败:', error.response?.data?.msg || error.message);
  }
}

// 列出文件函数
async function listFiles() {

  try {
  //  console.log('客户端的token', authToken);
    const response = await axios.get(`${serverURL}/api/dirs/list`, {
      headers: { 'Authorization': `Bearer ${authToken}` }  // 添加 Authorization 头

    });
 
    if (response.data.contents.length > 0) {
      console.log('当前目录文件:');
      response.data.contents.forEach((file) => {
        console.log(file);
      });
    } else {
      console.log('目录为空');
    }
  } catch (error) {
    console.error('列出文件失败:', error.response?.data?.msg || error.message);
  }
}
// 修改后的客户端代码：更新 authToken
async function changeDirectory(newDir) {
  try {
    const response = await axios.put(`${serverURL}/api/dirs/change`, { newDir }, {
      headers: { Authorization: `Bearer ${authToken}` }  // 继续使用 authToken
    });

    if (response.data.status === 0) {
      console.log(response.data.msg);

      // 更新 authToken，确保以后操作使用最新的 token
      authToken = response.data.token;  // 更新 token

    } else {
      console.log(response.data.msg);
    }
  } catch (error) {
    console.error('目录切换失败:', error.response?.data?.msg || error.message);
  }
}

// 远程打印当前路径函数
async function printRemotePath() {
  try {
    const response = await axios.get(`${serverURL}/api/dirs/pwd`, {
      headers: { 'Authorization': `Bearer ${authToken}` }  // 添加 Authorization 头
    });
    console.log('服务器当前路径:', response.data.currentPath);

  } catch (error) {
    console.error('获取服务器路径失败:', error.response?.data?.msg || error.message);
  }
}



// 捕获 `Ctrl+C` 事件来关闭 readline
rl.on('SIGINT', () => {
  rl.close();
  process.exit(0);
});

// 启动客户端
startCLI();



